
package com.dhcc.bpm.common.interceptor;

import com.dhcc.bpm.modules.system.service.ISerialNumberService;
import com.dhcc.bpm.modules.system.service.IUserService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.secure.BladeUser;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.api.ResultCode;
import org.springblade.core.tool.constant.BladeConstant;
import org.springblade.core.tool.jackson.JsonUtil;
import org.springblade.core.tool.utils.WebUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.http.MediaType;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName TokenInterceptor
 * @Description 配置类
 * @Author lijiacheng
 * @Date 2020/2/21 0021 15:16
 * @Version V1.0
 * @Copyright: 2020 东华软件 . All rights reserved.
 **/

@Slf4j
@Component
@AllArgsConstructor
public class TokenInterceptor extends HandlerInterceptorAdapter {

	@Autowired
	IUserService userService;
	@Autowired
	ISerialNumberService serialNumberService;
	private JdbcTemplate jdbcTemplate;
	private static final String EXP_SQE = "expSeq";

	/**
	 * 获取导出数据标识
	 */
	private  static String DATA_BY_EXP_SEQ = "select max_serial from opc_serial_number where module_code = 'exp_seq'";

	private StringRedisTemplate stringRedisTemplate;
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
		ValueOperations<String, String> opsForValue = stringRedisTemplate.opsForValue();
		//使用token验证登录逻辑
		BladeUser bladeUser = AuthUtil.getUser();
		if (null != bladeUser) {
			if(opsForValue.get(EXP_SQE) == null){
				List<String> expSeqList = jdbcTemplate.queryForList(DATA_BY_EXP_SEQ, String.class);
				opsForValue.set(EXP_SQE, expSeqList.get(0));
//				String expSeq = serialNumberService.generateSerialNumberByModelCode("exp_seq");
//				opsForValue.set(EXP_SQE, expSeq);
			}
			bladeUser.setExpSeq(opsForValue.get(EXP_SQE));

			String token = request.getHeader("Blade-Auth");
			if(token == null){
				token = request.getParameter("Blade-Auth");
			}
			String authToken = opsForValue.get(bladeUser.getAccount() + "@token");
			R result = null;
			if(token == null || authToken == null ){
				log.warn("token已失效，请求接口：{}，请求IP：{}，请求参数：{}", request.getRequestURI(), WebUtil.getIP(request), JsonUtil.toJson(request.getParameterMap()));

				result = R.fail(ResultCode.UN_AUTHORIZED);
				response.setCharacterEncoding(BladeConstant.UTF_8);
				response.setHeader(BladeConstant.CONTENT_TYPE_NAME, MediaType.APPLICATION_JSON_UTF8_VALUE);
				response.setStatus(HttpServletResponse.SC_OK);
				try {
					response.getWriter().write(Objects.requireNonNull(JsonUtil.toJson(result)));
				} catch (IOException ex) {
					log.error(ex.getMessage());
				}
				return false;
			}
			token = token.replace("bearer ","");
			if(!token.equals(authToken)){
				log.warn("账号异地登录，请求接口：{}，请求IP：{}，请求参数：{}", request.getRequestURI(), WebUtil.getIP(request), JsonUtil.toJson(request.getParameterMap()));

				result = R.fail(ResultCode.ACCOUNT_REMOTE_LOGIN);
				response.setCharacterEncoding(BladeConstant.UTF_8);
				response.setHeader(BladeConstant.CONTENT_TYPE_NAME, MediaType.APPLICATION_JSON_UTF8_VALUE);
				response.setStatus(HttpServletResponse.SC_OK);
				try {
					response.getWriter().write(Objects.requireNonNull(JsonUtil.toJson(result)));
				} catch (IOException ex) {
					log.error(ex.getMessage());
				}
				return false;
			}
			log.info("token:{}", token);
			//将账号存入redis
			opsForValue.set(token, bladeUser.getAccount() + "@workFlowRole", 3600, TimeUnit.SECONDS);
			//工作流校验用户是否拥有流程设计权限
			opsForValue.set(bladeUser.getAccount() + "@workFlowRole", opsForValue.get(bladeUser.getAccount() + "@workFlowRole"), 3600, TimeUnit.SECONDS);
			opsForValue.set(bladeUser.getAccount() + "@token", authToken, 3600, TimeUnit.SECONDS);
			return true;
		} else {
			log.warn("签名认证失败，请求接口：{}，请求IP：{}，请求参数：{}", request.getRequestURI(), WebUtil.getIP(request), JsonUtil.toJson(request.getParameterMap()));
			R result = R.fail(ResultCode.UN_AUTHORIZED);
			response.setCharacterEncoding(BladeConstant.UTF_8);
			response.setHeader(BladeConstant.CONTENT_TYPE_NAME, MediaType.APPLICATION_JSON_UTF8_VALUE);
			response.setStatus(HttpServletResponse.SC_OK);
			try {
				response.getWriter().write(Objects.requireNonNull(JsonUtil.toJson(result)));
			} catch (IOException ex) {
				log.error(ex.getMessage());
			}
			return false;
		}
	}

}
